<template>
    <div class="search-container">
        <el-select-v2
            v-model="selectedValues"
            multiple
            filterable
            remote
            :options="suggestions"
            :remote-method="onRemoteSearch"
            :reserve-keyword="false"
            clearable
            placeholder="请输入关键词"
            class="w-full"
            @clear="handleClear"
            @change="handleChange"
        >
            <template #default="{ item }">
                <div v-if="!item.isMore" class="flex items-center">
                    <el-tag type="info" size="small" class="mr-2">
                        {{ groupDict[item.value.group] }}
                    </el-tag>
                    <span>{{ item.value.value }}</span>
                </div>
                <div
                    v-else
                    class="autocomplete-more-item"
                    @mousedown.prevent="handleMore(item.group)"
                >
                    <em
                        >{{ item.count }} more {{ item.group }}, click to load
                        more</em
                    >
                </div>
            </template>
        </el-select-v2>
    </div>
</template>

<script setup lang="ts" name="EsSearchBar">
    import { ref, reactive } from "vue";
    import debounce from "lodash.debounce";
    import { get } from "../axios/api";
    import { groupDict } from "@/common/util";

    interface SelectedValue {
        group: string;
        value: string;
    }
    interface OptionItem {
        label: string;
        value: SelectedValue | null; // null for isMore
        group?: string;
        isMore?: boolean;
        count?: number;
        disabled?: boolean;
    }

    const emit = defineEmits<{
        (e: "select", payload: any): void;
        (e: "clear"): void;
    }>();

    /* v-model 保存对象数组：[{group, value}, ...] */
    const selectedValues = ref<SelectedValue[]>([]);

    /* 用于保存上次的 query（当用户键入时更新），programmatic 调用会使用它 */
    const lastQuery = ref("");

    /* 后端原始分组数据 */
    const results: Record<string, string[]> = reactive({
        SampleID: [],
        gender: [],
        subType: [],
        treatment: [],
    });

    /* 哪些组已展开 */
    const expanded:any = reactive({
        SampleID: false,
        gender: false,
        subType: false,
        treatment: false,
    });

    /* options 列表（必须为数组） */
    const suggestions = ref<OptionItem[]>([]);

    /* 将 selectedValues 按 group 合并：{ group: [val1, val2] } */
    function buildGroupedFromSelected(
        vals: SelectedValue[] = selectedValues.value
    ) {
        const grouped: Record<string, string[]> = {};
        (vals || []).forEach((it) => {
            if (!it || !it.group) return;
            if (!grouped[it.group]) grouped[it.group] = [];
            if (!grouped[it.group].includes(it.value))
                grouped[it.group].push(it.value);
        });
        return grouped;
    }

    /* 真实请求函数：立即调用后端，更新 results + suggestions */
    async function fetchOptionsApi(
        q: string,
        selectedGrouped: Record<string, string[]>
    ) {
        try {
            lastQuery.value = q ?? "";
            // 后端约定：selected 以 JSON 字符串接受 grouped 对象
            const params = {
                q: q ?? "",
                selected: JSON.stringify(selectedGrouped || {}),
            };
            const res = await get("/clinical-data/search/", params);
            // res 应返回 { SampleID: [...], gender: [...], ... }
            Object.assign(results, res || {});
            // 新搜索默认重置展开（你可以根据需要保留 expand 状态）
            Object.keys(expanded).forEach((k) => (expanded[k] = false));
            buildSuggestions();
        } catch (e) {
            console.error("fetchOptionsApi error", e);
        }
    }

    /* 防抖包装，供用户键入时调用 */
    const fetchOptionsDebounced = debounce((q: string) => {
        const grouped = buildGroupedFromSelected();
        fetchOptionsApi(q, grouped);
    }, 300);

    /* remote-method 入口（el-select-v2 调用） */
    function onRemoteSearch(q: string) {
        fetchOptionsDebounced(q);
    }

    /* 构造 suggestions：注意排除已选项（以 group+value 比对） */
    function buildSuggestions() {
        const list: OptionItem[] = [];
        const groups = ["SampleID", "gender", "subType", "treatment"];
        groups.forEach((grp) => {
            const arr = results[grp] || [];
            if (!arr.length) return;

            // 过滤已被选的（用 selectedValues）
            const selectedSet = new Set(
                selectedValues.value
                    .filter((s) => s.group === grp)
                    .map((s) => s.value)
            );

            const filtered = arr.filter((v) => !selectedSet.has(v));

            if (expanded[grp]) {
                // 展开全部
                filtered.forEach((v) =>
                    list.push({
                        label: `${groupDict[grp]}: ${v}`,
                        value: { group: grp, value: v },
                        group: grp,
                        isMore: false,
                        disabled: false,
                    })
                );
            } else {
                // 只显示前三 + more
                filtered.slice(0, 3).forEach((v) =>
                    list.push({
                        label: `${groupDict[grp]}: ${v}`,
                        value: { group: grp, value: v },
                        group: grp,
                        isMore: false,
                        disabled: false,
                    })
                );
                if (filtered.length > 3) {
                    list.push({
                        label: `${groupDict[grp]}: ${filtered.length - 3} more`,
                        value: null,
                        group: grp,
                        isMore: true,
                        count: filtered.length - 3,
                        disabled: true,
                    });
                }
            }
        });

        suggestions.value = list;
    }

    /* 点击 more 展开该组 */
    function handleMore(group: string) {
        expanded[group] = true;
        buildSuggestions();
    }

    /* 清空回调 */
    function handleClear() {
        // selectedValues 已被清空（v-model）
        emit("clear");
        // 刷新下拉（把 grouped 置空）
        fetchOptionsApi(lastQuery.value, {});
    }

    /* handleChange：当用户选择/取消时触发（v-model 已更新）
        功能：
        - 生成 grouped（按 group 合并）
        - 立即调用 fetchOptionsApi(lastQuery, grouped) 刷新下拉
        - emit('select', { grouped, raw })
    */
    function handleChange(newVals: SelectedValue[]) {
        const curr: SelectedValue[] = Array.isArray(newVals) ? newVals : [];
        const grouped = buildGroupedFromSelected(curr);

        // 立即调用后端（把 grouped 作为 selected 发送），更新 suggestions
        fetchOptionsApi(lastQuery.value, grouped);

        // 向父组件发出合并结果与增删项
        emit("select", {
            grouped,
            raw: curr,
        });
    }
</script>

<style scoped>
    .search-container {
        max-width: 100%;
        margin: 0 auto;
    }
    .autocomplete-more-item {
        width: 100%;
        color: #409eff;
        font-style: italic;
        padding: 4px 8px;
    }
</style>
